// MeasurementManager.cpp
#include "MeasurementManager.h"
#include <QPolygonF>
#include <QtMath>

/*
QVariantList MeasurementManager::smoothCurveOne(const QVariantList &points) {
    QVariantList result;
    if (points.size() < 3) return result;

    QVector<QPointF> pts;
    pts.reserve(points.size());

    // ✅ 改进: 兼容 QML {x:..., y:...} 格式
    for (const auto &v : points) {
        if (v.canConvert<QPointF>()) {
            pts.append(v.toPointF());
        } else {
            QVariantMap m = v.toMap();
            if (m.contains("x") && m.contains("y"))
                pts.append(QPointF(m["x"].toDouble(), m["y"].toDouble()));
        }
    }

    if (pts.size() < 3) return result;

    // Catmull-Rom 插值平滑曲线
    int segs = 20;
    for (int i = 0; i < pts.size(); ++i) {
        QPointF p0 = pts[(i - 1 + pts.size()) % pts.size()];
        QPointF p1 = pts[i];
        QPointF p2 = pts[(i + 1) % pts.size()];
        QPointF p3 = pts[(i + 2) % pts.size()];

        for (int j = 0; j < segs; ++j) {
            double t = (double)j / segs;
            double t2 = t * t, t3 = t2 * t;

            double x = 0.5 * ((2 * p1.x()) +
                              (-p0.x() + p2.x()) * t +
                              (2*p0.x() - 5*p1.x() + 4*p2.x() - p3.x()) * t2 +
                              (-p0.x() + 3*p1.x() - 3*p2.x() + p3.x()) * t3);

            double y = 0.5 * ((2 * p1.y()) +
                              (-p0.y() + p2.y()) * t +
                              (2*p0.y() - 5*p1.y() + 4*p2.y() - p3.y()) * t2 +
                              (-p0.y() + 3*p1.y() - 3*p2.y() + p3.y()) * t3);

            result.append(QPointF(x, y));
        }
    }

    return result;
}*/


QVariantList MeasurementManager::smoothCurveOne(const QVariantList &points)
{
    QVariantList result;
    if (points.size() < 3)
        return result;

    QVector<QPointF> pts;
    pts.reserve(points.size());

    // ✅ 支持 QML {x:..., y:...} 格式
    for (const auto &v : points) {
        if (v.canConvert<QPointF>()) {
            pts.append(v.toPointF());
        } else {
            QVariantMap m = v.toMap();
            if (m.contains("x") && m.contains("y"))
                pts.append(QPointF(m["x"].toDouble(), m["y"].toDouble()));
        }
    }

    if (pts.size() < 3)
        return result;

    bool closed = true;  // ✅ 闭合曲线支持
    int segs = 20;       // 每段插值细分
    double alpha = 0.5;  // 0.5 = centripetal（推荐）

    int n = pts.size();

    for (int i = 0; i < n; ++i) {
        QPointF p0 = pts[(i - 1 + n) % n];
        QPointF p1 = pts[i];
        QPointF p2 = pts[(i + 1) % n];
        QPointF p3 = pts[(i + 2) % n];

        // ✅ 计算非均匀参数 t0, t1, t2, t3
        auto tj = [&](double ti, const QPointF &pi, const QPointF &pj) {
            double dx = pj.x() - pi.x();
            double dy = pj.y() - pi.y();
            // |Pi - Pj|^alpha
            return ti + std::pow(dx * dx + dy * dy, alpha * 0.5);
        };

        double t0 = 0.0;
        double t1 = tj(t0, p0, p1);
        double t2 = tj(t1, p1, p2);
        double t3 = tj(t2, p2, p3);

        // ✅ 在 t1-t2 范围内插值
        for (int j = 0; j < segs; ++j) {
            double t = t1 + (t2 - t1) * (double)j / segs;

            QPointF A1 = ((t1 - t) / (t1 - t0)) * p0 + ((t - t0) / (t1 - t0)) * p1;
            QPointF A2 = ((t2 - t) / (t2 - t1)) * p1 + ((t - t1) / (t2 - t1)) * p2;
            QPointF A3 = ((t3 - t) / (t3 - t2)) * p2 + ((t - t2) / (t3 - t2)) * p3;

            QPointF B1 = ((t2 - t) / (t2 - t0)) * A1 + ((t - t0) / (t2 - t0)) * A2;
            QPointF B2 = ((t3 - t) / (t3 - t1)) * A2 + ((t - t1) / (t3 - t1)) * A3;

            QPointF C = ((t2 - t) / (t2 - t1)) * B1 + ((t - t1) / (t2 - t1)) * B2;

            result.append(C);
        }
    }

    // ✅ 如果闭合，则首尾相连
    if (closed && !result.isEmpty())
        result.append(result.first());

    return result;
}

/*
QVariantList MeasurementManager::smoothCurve(const QVariantList &points) {
    QVariantList result;
    if (points.size() < 3) return result;

    QVector<QPointF> pts;
    pts.reserve(points.size());

    // 支持 QML {x:..., y:...} 格式
    for (const auto &v : points) {
        if (v.canConvert<QPointF>()) {
            pts.append(v.toPointF());
        } else {
            QVariantMap m = v.toMap();
            if (m.contains("x") && m.contains("y"))
                pts.append(QPointF(m["x"].toDouble(), m["y"].toDouble()));
        }
    }

    if (pts.size() < 3) return result;

    // Step 1: 使用质心 + 极角排序，避免交叉
    QPointF centroid(0, 0);
    for (const auto &p : pts) centroid += p;
    centroid /= pts.size();

    std::sort(pts.begin(), pts.end(), [&](const QPointF &a, const QPointF &b) {
        double angleA = std::atan2(a.y() - centroid.y(), a.x() - centroid.x());
        double angleB = std::atan2(b.y() - centroid.y(), b.x() - centroid.x());
        return angleA < angleB;
    });

    QVector<QPointF> orderedPts = pts;
    orderedPts.append(orderedPts.first());  // 闭合曲线

    // 辅助函数：计算 t 值 (centripetal)
    auto tj = [](double ti, const QPointF &pi, const QPointF &pj, double alpha = 0.5) {
        double dx = pj.x() - pi.x();
        double dy = pj.y() - pi.y();
        return std::pow(std::sqrt(dx*dx + dy*dy), alpha) + ti;
    };

    // Step 2: Centripetal Catmull-Rom 插值
    int segs = 20;  // 每段细分点数，越大越平滑
    int n = orderedPts.size();

    for (int i = -1; i < n - 2; ++i) {
        QPointF p0 = orderedPts[(i + n) % n];
        QPointF p1 = orderedPts[(i + 1 + n) % n];
        QPointF p2 = orderedPts[(i + 2 + n) % n];
        QPointF p3 = orderedPts[(i + 3 + n) % n];

        double t0 = 0.0;
        double t1 = tj(t0, p0, p1);
        double t2 = tj(t1, p1, p2);
        double t3 = tj(t2, p2, p3);

        for (int j = 0; j < segs; ++j) {
            double t = t1 + (t2 - t1) * (double)j / segs;

            // 插值
            QPointF A1 = (t1 - t) / (t1 - t0) * p0 + (t - t0) / (t1 - t0) * p1;
            QPointF A2 = (t2 - t) / (t2 - t1) * p1 + (t - t1) / (t2 - t1) * p2;
            QPointF A3 = (t3 - t) / (t3 - t2) * p2 + (t - t2) / (t3 - t2) * p3;

            QPointF B1 = (t2 - t) / (t2 - t0) * A1 + (t - t0) / (t2 - t0) * A2;
            QPointF B2 = (t3 - t) / (t3 - t1) * A2 + (t - t1) / (t3 - t1) * A3;

            QPointF C  = (t2 - t) / (t2 - t1) * B1 + (t - t1) / (t2 - t1) * B2;

            result.append(C);
        }
    }

    return result;
}*/
/*
QVariantList MeasurementManager::smoothCurve(const QVariantList &points) {
    QVariantList result;
    if (points.size() < 3) return result;

    QVector<QPointF> pts;
    pts.reserve(points.size());

    // 支持 QML {x:..., y:...} 格式
    for (const auto &v : points) {
        if (v.canConvert<QPointF>()) {
            pts.append(v.toPointF());
        } else {
            QVariantMap m = v.toMap();
            if (m.contains("x") && m.contains("y"))
                pts.append(QPointF(m["x"].toDouble(), m["y"].toDouble()));
        }
    }

    if (pts.size() < 3) return result;

    // ✅ Step 1: 以 (400,400) 为圆心，按极角排序
    QPointF center(400, 400);
    std::sort(pts.begin(), pts.end(), [&](const QPointF &a, const QPointF &b) {
        double angleA = std::atan2(a.y() - center.y(), a.x() - center.x());
        double angleB = std::atan2(b.y() - center.y(), b.x() - center.x());
        return angleA < angleB;
    });

    // ✅ Step 2: Catmull-Rom 插值，生成平滑闭合曲线
    int segs = 20;
    int n = pts.size();
    for (int i = 0; i < n; ++i) {
        QPointF p0 = pts[(i - 1 + n) % n];
        QPointF p1 = pts[i];
        QPointF p2 = pts[(i + 1) % n];
        QPointF p3 = pts[(i + 2) % n];

        for (int j = 0; j < segs; ++j) {
            double t = (double)j / segs;
            double t2 = t * t, t3 = t2 * t;

            double x = 0.5 * ((2 * p1.x()) +
                              (-p0.x() + p2.x()) * t +
                              (2*p0.x() - 5*p1.x() + 4*p2.x() - p3.x()) * t2 +
                              (-p0.x() + 3*p1.x() - 3*p2.x() + p3.x()) * t3);

            double y = 0.5 * ((2 * p1.y()) +
                              (-p0.y() + p2.y()) * t +
                              (2*p0.y() - 5*p1.y() + 4*p2.y() - p3.y()) * t2 +
                              (-p0.y() + 3*p1.y() - 3*p2.y() + p3.y()) * t3);

            result.append(QPointF(x, y));
        }
    }

    return result;
}*/
QVariantList MeasurementManager::smoothCurve(const QVariantList &points,
                                             const QPointF &center) {
    QVariantList result;
    if (points.size() < 3) return result;

    QVector<QPointF> pts;
    pts.reserve(points.size());

    // ✅ 兼容 QML {x:..., y:...} 格式
    for (const auto &v : points) {
        if (v.canConvert<QPointF>()) {
            pts.append(v.toPointF());
        } else {
            QVariantMap m = v.toMap();
            if (m.contains("x") && m.contains("y"))
                pts.append(QPointF(m["x"].toDouble(), m["y"].toDouble()));
        }
    }

    if (pts.size() < 3) return result;

    // ✅ 按照极角排序，确保闭合不交叉
    std::sort(pts.begin(), pts.end(), [center](const QPointF &a, const QPointF &b) {
        double angleA = std::atan2(a.y() - center.y(), a.x() - center.x());
        double angleB = std::atan2(b.y() - center.y(), b.x() - center.x());
        return angleA < angleB;
    });

    // ✅ Catmull-Rom 插值平滑曲线
    int segs = 20;
    for (int i = 0; i < pts.size(); ++i) {
        QPointF p0 = pts[(i - 1 + pts.size()) % pts.size()];
        QPointF p1 = pts[i];
        QPointF p2 = pts[(i + 1) % pts.size()];
        QPointF p3 = pts[(i + 2) % pts.size()];

        for (int j = 0; j < segs; ++j) {
            double t = (double)j / segs;
            double t2 = t * t, t3 = t2 * t;

            double x = 0.5 * ((2 * p1.x()) +
                              (-p0.x() + p2.x()) * t +
                              (2*p0.x() - 5*p1.x() + 4*p2.x() - p3.x()) * t2 +
                              (-p0.x() + 3*p1.x() - 3*p2.x() + p3.x()) * t3);

            double y = 0.5 * ((2 * p1.y()) +
                              (-p0.y() + p2.y()) * t +
                              (2*p0.y() - 5*p1.y() + 4*p2.y() - p3.y()) * t2 +
                              (-p0.y() + 3*p1.y() - 3*p2.y() + p3.y()) * t3);

            result.append(QPointF(x, y));
        }
    }

    return result;
}

double MeasurementManager::polygonArea(const QVector<QPointF> &pts) {
    double area = 0;
    for (int i = 0; i < pts.size(); i++) {
        QPointF p1 = pts[i];
        QPointF p2 = pts[(i + 1) % pts.size()];
        area += (p1.x() * p2.y() - p2.x() * p1.y());
    }
    return qAbs(area) / 2.0;
}

double MeasurementManager::area(const QVariantList &points) {
    QVector<QPointF> pts;
    for (auto &v : points) pts.append(v.toPointF());
    return polygonArea(pts);
}

double MeasurementManager::polygonArea(const QVariantList &curvePoints) {
    if (curvePoints.size() < 3) return 0.0;

    QVector<QPointF> pts;
    pts.reserve(curvePoints.size());
    for (const auto &v : curvePoints) {
        if (v.canConvert<QPointF>()) {
            pts.append(v.toPointF());
        } else {
            QVariantMap m = v.toMap();
            if (m.contains("x") && m.contains("y"))
                pts.append(QPointF(m["x"].toDouble(), m["y"].toDouble()));
        }
    }

    double area = 0.0;
    for (int i = 0; i < pts.size(); ++i) {
        const QPointF &p1 = pts[i];
        const QPointF &p2 = pts[(i + 1) % pts.size()];
        area += p1.x() * p2.y() - p2.x() * p1.y();
    }
    return std::abs(area) * 0.5;
}
